#include <printThings.h>
#include <sharedMem.h>

int posX = 0;
int posY = 0;

unsigned char color = STANDARDTEXTSTYLE;

void updatePositions(){
}

void setColor(unsigned char c) {
    color = c;
}

void setStandard() {
    color = STANDARDTEXTSTYLE;
}


void cls(void) {
    posX = posY = 0;
    char *vidMem = (char *)0xB8000;

    int i = 0;
    for (i = 0; i < 4000; i++) {
        vidMem[i] = 0x0;
    }
    updatePosXY(posX, posY);
}

void newLine() {
    posY++;
    posX = 0;
    updatePosXY(posX, posY);
}

void kPrintChar(char c) {
    char *vidMem = (char *)0xB8000;

    if (c == '\n') {
        newLine();
        return;
    }

    if (posX > 80) {
        newLine();
    }


    if (posY >= 25) {
        int i, j;
        for (i = 1; i < 25; i++) {
            for (j = 0; j < 80; j++) {
                int offOld = (i * 80 + j) * 2;
                int offNew = ((i-1) * 80 +j) * 2;
                vidMem[offNew] = vidMem[offOld];
                vidMem[offNew + 1] = vidMem[offOld + 1];
            }
        }
        /*letzte zeile clsn*/
        for (i = 0; i < 80; i++)
            vidMem[(24 * 80 + i) * 2] = vidMem[((24 * 80 + i) * 2) + 1] = 0x0;
        posY = 24;
    }



    int off = (posY * 80 + posX) * 2;
    vidMem[off] = c;
    vidMem[off + 1] = color;
    posX++;
    updatePosXY(posX, posY);
}


void printNumberUHex(unsigned int value) {
    unsigned int erg[10];
    char nr[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    if (value == 0) {
        kPrintChar('0');
        return;
    }

    int i = 0;

    while (value != 0) {
        erg[i] = value % 16;
        value = value / 16;
        i++;
    }

    kPrintChar('0');
    kPrintChar('x');

    i--;
    int i2;
    for (i2 = i; i2 >= 0; i2--) {
        kPrintChar(nr[erg[i2]]);
    }
}

void printNumberHex(int value) {
    int erg[10];
    unsigned char neg = 0;
    char nr[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    if (value == 0) {
        kPrintChar('0');
        return;
    }

    if (value < 0) {
        neg = 1;
        value = -value;
        kPrintChar('-');
    }

    int i = 0;
    while (value != 0) {
        erg[i] = value % 16;
        value = value / 16;
        i++;
    }

    kPrintChar('0');
    kPrintChar('x');

    i--;
    int i2;
    for (i2 = i; i2 >= 0; i2--) {
        kPrintChar(nr[erg[i2]]);
    }
}

void printNumber(int value) {
    int erg[10];
    unsigned char neg = 0;
    char nr[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

    if (value == 0) {
        kPrintChar('0');
        return;
    }

    if (value < 0) {
        neg = 1;
        value = -value;
        kPrintChar('-');
    }

    int i = 0;
    while (value != 0) {
        erg[i] = value % 10;
        value = value / 10;
        i++;
    }

    i--;
    int i2;
    for (i2 = i; i2 >= 0; i2--) {
        kPrintChar(nr[erg[i2]]);
    }
}


void printf2(const char *output, int **args) {
    while (*output) {
        if (*output == '\0')
            return;
        if (*output == '%') {
            *output++;
            switch (*output) {
            case 'd': {
                /*number*/
                int value = (int)*(*args)++;
                printNumber(value);
                *output++;
                break;
            }
            case 'c': {
                /*character*/
                char c = (char)*(*args)++;
                kPrintChar(c);
                *output++;
                break;
            }
            case 'x': {
                /*hexadezimal*/
                int value = (int)*(*args)++;
                printNumberHex(value);
                *output++;
                break;
            }

            case 'y': {
                /*hexadezimal*/
                unsigned int value = 0;
                value = (int)*(*args)++;
                printNumberUHex(value);
                *output++;
                break;
            }
            case 's': {
                /*string*/
                *output++;
                printf((char*)*(*args)++);
                break;
            }
            }
        } else {
            kPrintChar(*output);
            *output++;
        }
    }
}

void printf(const char* output, ...) {
    /*diese methode hab ich aus meinem frueheren os namens os0
     ka wie ich drauf gekommen bin aber es funkt*/
    getPositionsFromSharedMem(&posX, &posY);
    int *args = ((int*)&output) + 1;
    printf2(output, &args);
}

void kPrint(char *string) {

    int i;

    for (i = 0; string[i] != '\0';i++) {
        kPrintChar(string[i]);
    }
}
